package cn.wolf.tools;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.widget.ImageView;
import cn.wolf.http.ImageGetter;
import cn.wolf.http.ProgressListener;
import cn.wolf.http.entity.BitmapProgress;

public abstract class ImageFactory {

	protected Context mContext;

	public abstract String getOperateDir();

	public abstract void cacheBitmap(Bitmap cache, String cacheKey);

	public abstract Bitmap getCache(String cacheKey);

	public abstract int bitmapResourceIdDef();

	public final String getKey(String str) {
		return MD5.getMD5Str(str);
	}

	public final String getFilePath(String fileName) {
		return getOperateDir() + fileName;
	}

	// 无压缩图片
	public Bitmap loadBitmap(final View view, final String url, String cacheKey) {
		return loadBitmap(view, url, cacheKey, bitmapResourceIdDef());
	}

	public Bitmap loadBitmap(final View view, final String url, String cacheKey,
			final ProgressListener<BitmapProgress> listener) {
		return loadBitmap(view, url, cacheKey, listener, false, 0, bitmapResourceIdDef());
	}

	// 无压缩图片
	public Bitmap loadBitmap(final View view, final String url, final String cacheKey, final int resId) {
		return loadBitmap(view, url, cacheKey, new ProgressListener<BitmapProgress>() {
			@Override
			public void onPostExecute(BitmapProgress entity) {
				if (entity != null) {
					setImageView(cacheKey, view, entity.getBitmap(), resId);
					cacheBitmap(entity.getBitmap(), cacheKey);
				}
			}

			@Override
			public void onPreExecute(BitmapProgress entity) {
			}

			@Override
			public void onProgressUpdate(BitmapProgress entity) {
			}
		}, false, 0, resId);
	}

	public Bitmap loadBitmap(final View view, final String url, String cacheKey,
			boolean isCompress, int junst) {
		return loadBitmap(view, url, cacheKey, isCompress, junst, bitmapResourceIdDef());
	}

	// 压缩图片
	public Bitmap loadBitmap(final View view, final String url, final String cacheKey,
			boolean isCompress, int junst, final int resId) {
		return loadBitmap(view, url, cacheKey, new ProgressListener<BitmapProgress>() {
			@Override
			public void onPostExecute(BitmapProgress entity) {
				if (entity != null) {
					setImageView(cacheKey, view, entity.getBitmap(), resId);
					cacheBitmap(entity.getBitmap(), getKey(url));
				}
			}

			@Override
			public void onPreExecute(BitmapProgress entity) {
			}

			@Override
			public void onProgressUpdate(BitmapProgress entity) {
			}
		}, isCompress, junst, resId);
	}

	protected Bitmap loadBitmap(final View view, final String url, final String cacheKey,
			final ProgressListener<BitmapProgress> listener, boolean isCompress, int junst,
			int resId) {
		Bitmap bitmap = null;
		if (view == null) {
			Log.i("loadBitmap view is null.");
			return bitmap;
		}

		if (StringUtil.isEmpty(url)) {
			Log.i("loadBitmap url is null.");
			return bitmap;
		}

		// load from cache
		bitmap = getCache(cacheKey);
		if (bitmap != null) {
			setImageView(cacheKey, view, bitmap, resId);
			return bitmap;
		}

		// load from sdacrd
		bitmap = readFile(cacheKey, isCompress, junst);
		if (bitmap != null) {
			setImageView(cacheKey, view, bitmap, resId);
			cacheBitmap(bitmap, cacheKey);
			return bitmap;
		}

		// load from network
		loadBitmapNetWork(url, cacheKey, listener, isCompress, junst);
		return bitmap;
	}

	protected final Bitmap readFile(String fileName, boolean isCompress, int junst) {
		Bitmap bitmap = null;
		if (SdCardTool.isMounted()) {
			String pathName = getFilePath(fileName);
			if (isCompress) {
				bitmap = compressBitmap(pathName, junst);
			} else {
				bitmap = decodeFile(pathName);
			}
		}
		return bitmap;
	}

	protected final void loadBitmapNetWork(final String url, final String cacheKey,
			final ProgressListener<BitmapProgress> listener, boolean isCompress, int junst) {

		if (StringUtil.isEmpty(url))
			return;

		Log.d("download bitmap, url: " + url);

		if (SdCardTool.isMounted()) { // sd卡挂载
			ImageGetter getter = new ImageGetter(getOperateDir(), cacheKey, isCompress, junst);
			getter.setProgressListener(new ProgressListener<BitmapProgress>() {
				@Override
				public void onPreExecute(BitmapProgress entity) {
					if (listener != null) {
						listener.onPreExecute(entity);
					}
				}

				@Override
				public void onProgressUpdate(BitmapProgress progress) {
					if (listener != null) {
						listener.onProgressUpdate(progress);
					}
				}

				@Override
				public void onPostExecute(BitmapProgress progress) {
					if (listener != null) {
						listener.onPostExecute(progress);
					}
					// cacheBitmap(progress.getBitmap(), cacheKey);
				}
			});
			getter.execute(url);

		} else { // sd卡未挂载
			Log.w("sdcard unmounted.");
			ImageGetter getter = new ImageGetter(isCompress, junst);
			getter.setProgressListener(new ProgressListener<BitmapProgress>() {

				@Override
				public void onPreExecute(BitmapProgress entity) {
					if (listener != null) {
						listener.onPreExecute(entity);
					}
				}

				@Override
				public void onProgressUpdate(BitmapProgress progress) {
					if (listener != null) {
						listener.onProgressUpdate(progress);
					}
				}

				@Override
				public void onPostExecute(BitmapProgress progress) {
					if (listener != null) {
						listener.onPostExecute(progress);
					}
				}
			});
			getter.execute(url);
		}
	}

	protected final Bitmap decodeFile(String pathName) {
		return BitmapFactory.decodeFile(pathName);
	}

	/**
	* 设置对应图片到view中
	* @param view
	* @param bitmap
	*/
	protected void setImageView(String cacheKey, View view, Bitmap bitmap, int resId) {

		if (view == null) {
			return;
		}

		if (bitmap == null) { // 获取默认图片
			if (resId == 0)
				resId = bitmapResourceIdDef();

			if (view instanceof ImageView) {
				ImageView imageView = (ImageView) view;
				imageView.setImageResource(resId);
			} else {
				view.setBackgroundResource(resId);
			}
			return;
		}

		if (view instanceof ImageView) {
			ImageView imageView = (ImageView) view;
			imageView.setImageBitmap(bitmap);
		} else {
			BitmapDrawable drawable = new BitmapDrawable(bitmap);
			view.setBackgroundDrawable(drawable);
		}
		view.setVisibility(View.VISIBLE);
	}

	/**
	* 如图片太大，根据文件流压缩读取
	* @param in
	* @return
	* @throws IOException
	*/
	public final static Bitmap compressBitmap(InputStream in, int junst) {
		Bitmap bitmap = null;
		byte[] datas = null;
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		try {

			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = in.read(buffer)) != -1) {
				outStream.write(buffer, 0, len);
			}

			datas = outStream.toByteArray();
			Options option = new Options();
			option.inJustDecodeBounds = true;
			bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length, option);

			int be = 0;
			if (option.outWidth > junst) {
				be = option.outWidth / junst;
			}
			if (be <= 0) {
				be = 1;
			}
			option.inJustDecodeBounds = false;
			option.inSampleSize = be;
			bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length, option);
		} catch (IOException e) {
			Log.e(e.getMessage(), e);
		} finally {
			StreamUtil.closeSilently(in);
			StreamUtil.closeSilently(outStream);
			datas = null;
		}

		return bitmap;
	}

	/**
	* 如图片太大，根据文件路径压缩读取
	* @param filePath
	* @return
	*/
	public final static Bitmap compressBitmap(String pathName, int junst) {
		Bitmap bitmap;
		Options option = new Options();
		option.inJustDecodeBounds = true;
		bitmap = BitmapFactory.decodeFile(pathName, option);
		int sampleSize = 0;
		if (option.outWidth > junst) {
			sampleSize = option.outWidth / junst;
		}
		if (sampleSize <= 0) {
			sampleSize = 1;
		}
		option.inSampleSize = sampleSize;
		option.inJustDecodeBounds = false;
		bitmap = BitmapFactory.decodeFile(pathName, option);
		return bitmap;
	}
}
